﻿// ===============================================================================
// XCI.NET 西安交通信息WinForm开发框架 2018 版权所有
// ===============================================================================
using System;
using System.Reflection;
using XCI.Helper;

namespace XCI.Core
{
    /// <summary>
    /// 方法调用句柄
    /// </summary>
    /// <param name="target">对象实例</param>
    /// <param name="paramters">参数</param>
    /// <returns>返回值</returns>
    public delegate object FastInvokeHandler(object target, params object[] paramters);

    /// <summary>
    /// 对象包装属性操作
    /// </summary>
    public sealed class FastProperty
    {
        /// <summary>
        /// Get委托
        /// </summary>
        private FastInvokeHandler _getHandler;

        /// <summary>
        /// Set委托
        /// </summary>
        private FastInvokeHandler _setHandler;

        /// <summary>
        /// 初始化对象包装属性
        /// </summary>
        /// <param name="property">属性元数据</param>
        public FastProperty(PropertyInfo property)
        {
            Property = property;
        }

        /// <summary>
        /// 属性对象
        /// </summary>
        public PropertyInfo Property { get; private set; }

        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="instanse">对象实例</param>
        /// <returns>属性值</returns>
        public object Get(object instanse)
        {
            if (Property == null) return null;
            if (_getHandler == null)
            {
                _getHandler = ObjectHelper.GetFastInvoker(Property.GetGetMethod());
            }
            return _getHandler(instanse, null);
        }

        /// <summary>
        /// 设置属性值
        /// </summary>
        /// <param name="instanse">对象实例</param>
        /// <param name="value">属性值</param>
        public void Set(object instanse, object value)
        {
            if (Property == null) return;
            if (!ObjectHelper.IsNullableType(Property.PropertyType) && (value == DBNull.Value || value == null))
            {
                throw new Exception(string.Format("属性{0}不允许为空,但给定的值为空值,无法赋值", Property.Name));
            }
            if (_setHandler == null)
            {
                _setHandler = ObjectHelper.GetFastInvoker(Property.GetSetMethod());
            }
            if (_setHandler == null) return;
            try
            {
                _setHandler(instanse, ObjectHelper.ConvertObjectValue(value, Property.PropertyType));
            }
            catch (Exception e)
            {
                var debugMessage = string.Format("设置属性{0}的值时发生异常,{1}", Property.Name, e.Message);
                throw new Exception(debugMessage, e);
            }
        }
    }

    /// <summary>
    /// 对象包装方法
    /// </summary>
    public sealed class FastMethod
    {
        /// <summary>
        /// 方法调用委托
        /// </summary>
        private FastInvokeHandler _callHandler;

        /// <summary>
        /// 初始化对象包装方法
        /// </summary>
        /// <param name="method">方法元数据</param>
        public FastMethod(MethodInfo method)
        {
            Method = method;
        }

        /// <summary>
        /// 方法对象
        /// </summary>
        public MethodInfo Method { get; private set; }

        /// <summary>
        /// 调用
        /// </summary>
        /// <param name="instanse">对象实例</param>
        /// <param name="parameters">参数</param>
        /// <returns>调用返回值</returns>
        public object Call(object instanse, params object[] parameters)
        {
            if (_callHandler == null)
            {
                _callHandler = ObjectHelper.GetFastInvoker(Method);
            }
            return _callHandler(instanse, parameters);
        }
    }
}